package com.countertack.forensics;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.sql.ResultSet;
import java.util.UUID;

import org.apache.commons.net.ftp.FTPClient;

import com.countertack.impala.ImpalaConnector;
import com.countertack.ssh.SSHManager;
import com.countertack.utils.Configuration;
import com.countertack.utils.HttpClientUtils;
import com.countertack.vmware.VMWareConnector;
import com.vmware.vim25.mo.VirtualMachine;

public class FTPForensic {

	public static void main(String[] args) throws Exception {
		if (args.length <= 0) {

			System.out.println("configuration details missed !");
			return;
		}
		StringBuffer testCaseResult = new StringBuffer();
		String configFilePath = args[0];
		// String configFilePath="C:\\Users\\user\\Desktop\\config.properties";
		Configuration.loadProperties(configFilePath);
		String vmUser = Configuration.getProperty("vmuser");

		String vmPassword = Configuration.getProperty("vmpassword");

		ImpalaConnector iConnector;

		iConnector = ImpalaConnector
				.createImpalaConnectorInstance(Configuration
						.getProperty("sentinelehost"));
		InetAddress address = InetAddress.getByName(Configuration
				.getProperty("sentinelehost"));
		String sentenelIp = address.getHostAddress();
		System.out.println(address.getHostAddress());

		// connect to esxi and starting virtual machines

		VMWareConnector esxiConnector = new VMWareConnector(
				Configuration.getProperty("esxi"));
		// poweredOn
		final VirtualMachine endPointMachine = esxiConnector
				.getVirtualMachineByname(Configuration.getProperty("vmname"));

		// win7x64-sym-2
		System.out.println("power state >>>"
				+ endPointMachine.getRuntime().powerState);

		String endpointMachineStatus = esxiConnector
				.getVirtualMachineStatus(endPointMachine);

		if (endpointMachineStatus == null) {

			System.out.println("Power on  endpoint machine .....");

			esxiConnector.startVirtualMachine(endPointMachine);

			Thread.sleep(600000);

		} else {

			if ("notRunning".equalsIgnoreCase(endpointMachineStatus)) {

				esxiConnector.reStartVirtualMachine(endPointMachine);

				System.out.println("Rebooting endpoint machine .....");

				Thread.sleep(600000);

			}

		}

		// initialising ssh to virtual machines

		System.out.println("ipdsdsmmfd>>>"
				+ endPointMachine.getGuest().ipAddress);

		final SSHManager endpointSsh = new SSHManager(vmUser, vmPassword,
				endPointMachine.getGuest().ipAddress);
		endpointSsh.connect();

		// install agent
		endpointSsh.copyFile(Configuration.getProperty("driverpath"),
				"CounterTack Agent Installer Hiding.exe");

		endpointSsh.runCommand("cmd /c \"C:\\Users\\" + vmUser
				+ "\\CounterTack Agent Installer Hiding.exe\" /S /HOST:"
				+ sentenelIp + " /PORT:443");

		System.out.println("Installing agent on endpoint");
		Thread.sleep(120000);

		String eId = null;
		ResultSet endpointIdRes = iConnector
				.executeQueryAndReturnResults("select id from endpoints where ip='"
						+ endPointMachine.getGuest().ipAddress
						+ "'"
						+ " and status='ON' and ip is not null order by time_started asc limit 1");

		while (endpointIdRes.next()) {
			try {
				eId = endpointIdRes.getString(1);
			} catch (Exception e) {

			}

			System.out.println("endpoint Id>>>>>>" + eId);
			testCaseResult.append("endpoint Id>>>>>>" + eId + "\n");

		}

		if (eId == null) {

			System.out.println("endpoint is not installed");
			testCaseResult.append("endpoint is not installed \n");
			addResultsToLog(testCaseResult);

			System.exit(0);

		}

		pauseEndpoint(eId);
		Thread.sleep(60000);
		endpointSsh.closeSession();
		endpointSsh.doReconnect = false;
		// retriving endpoint id

		// applying profile to endpoint

		String payload = "{ " + "  \"type\": \"apply_profile_to_endpoints\", "
				+ "  \"profile\":\"" + Configuration.getProperty("profilename")
				+ "\", " + "  \"endpoints\":[ " + "\"" + eId + "\" " + "] "
				+ "} ";
		System.out.println("payload>>>" + payload);
		//

		HttpClientUtils.composePostRequest(
				Configuration.getProperty("restapirooturi")
						+ "/endpoints/command", payload);

		Thread.sleep(3000);
		// resume endpoint

		resumeEndpoint(eId);
		String uuid = UUID.randomUUID().toString();

		Thread.sleep(30000);

		// new Thread(new Runnable() {
		//
		// @Override
		// public void run() {
		// String command[] = { "ftp ",
		// endPointMachine.getGuest().ipAddress };
		//
		// StringBuffer output = new StringBuffer();
		// try {
		// Process p = Runtime.getRuntime().exec(command);
		// InputStreamReader ir = new InputStreamReader(
		// p.getInputStream());
		// int outputChar = 0;
		// while ((outputChar = ir.read()) != -1) {
		// output.append((char) outputChar);
		// if (!ir.ready()) { // If the next read is not
		// // guaranteed, come out of loop.
		// break;
		// }
		// }
		// ir.close();
		// System.out.println("FTP is connected");
		//
		// } catch (IOException e) {
		// e.printStackTrace();
		// }
		// System.out.println("ftp output >>>>>" + output.toString());
		//
		// }
		//
		// }).start();

		// get an ftpClient object
		uploadFile(uuid, endPointMachine.getGuest().ipAddress);

		appendFile(uuid, endPointMachine.getGuest().ipAddress);

		Thread.sleep(6000);

		ResultSet brs = iConnector
				.executeQueryAndReturnResults("select hex(id) from behaviors where uri like '%"
						+ eId + "%'  order by event_start_time desc limit 1");
		String bhid = null;

		while (brs.next()) {
			bhid = brs.getString(1);

		}
		System.out.println("behavior id>>>>" + bhid);
		testCaseResult.append("behavior id>>>>" + bhid + "\n");

		// verifying netcat client
		ResultSet netcatpros = iConnector
				.executeQueryAndReturnResults("select target_thread_process_name from behaviors_denorm where hex(behavior_id)='"
						+ bhid
						+ "' and behavior_id is not null and is_origin=1");
		boolean inbound = false;

		while (netcatpros.next()) {
			String path = netcatpros.getString(1);

			if (path != null) {

				System.out.println("path>>>" + path);
				if (path.contains("File")) {

					inbound = true;

					break;

				}

			}
		}
		if (inbound) {

			System.out.println("New origin for inbound(FTP)----------->Pass");
			testCaseResult
					.append("New origin for inbound(FTP)----------->Pass \n");

		} else {

			System.out.println("New origin for inbound(FTP)----------->Fail");
			testCaseResult
					.append("New origin for inbound(FTP)----------->Fail \n");
			// System.exit(0);

		}

		ResultSet flwrrs = iConnector
				.executeQueryAndReturnResults("select target_file_path from behaviors_denorm where hex(behavior_id) = '"
						+ bhid
						+ "' and behavior_id is not null and is_key=1 group by target_file_path");
		boolean fwrite = false;
		while (flwrrs.next()) {
			String fn = flwrrs.getString(1);

			if (fn != null) {

				System.out.println("fname>>>" + fn);
				if (fn.contains("test_file" + uuid + ".txt")) {

					// System.out.println("Inbound passed");
					fwrite = true;
					break;
					// System.exit(0);
					// return;

				}

			}
		}

		if (fwrite) {

			System.out.println("New Key event for file write------->Pass");
			testCaseResult
					.append("New Key event for file write------->Pass \n");

		} else {

			System.out.println("New Key event for file write------->Fail");
			testCaseResult
					.append("New Key event for file write------->Fail \n");
			// System.exit(0);

		}

		addResultsToLog(testCaseResult);
		System.exit(0);

	}

	public static void addResultsToLog(StringBuffer vals) {
		File testCaseResFile = new File("FTP_forrensic_result_"
				+ Configuration.getProperty("vmname") + ".txt");

		try {
			testCaseResFile.createNewFile();
			FileOutputStream fout = new FileOutputStream(testCaseResFile);

			//

			fout.write(vals.toString().getBytes());

			fout.flush();
			fout.close();

		} catch (Exception e) {

			e.printStackTrace();

		}

	}

	public static void pauseEndpoint(String eid) throws Exception {

		String pause = "{ " + "  \"type\":\"pause_many\", "
				+ "  \"endpoints\":[ " + "\"" + eid + "\" " + " ] " + "} ";

		HttpClientUtils.composePostRequest(
				Configuration.getProperty("restapirooturi")
						+ "/endpoints/command", pause);

	}

	public static void resumeEndpoint(String eid) throws Exception {

		String resume = "{ " + "  \"type\":\"resume_many\", "
				+ "  \"endpoints\":[ " + "    \"" + eid + "\" " + "] " + "} ";

		HttpClientUtils.composePostRequest(
				Configuration.getProperty("restapirooturi")
						+ "/endpoints/command", resume);

	}

	public static void uploadFile(String uuid, String ip) {

		FTPClient ftpClient = new FTPClient();
		FileInputStream inputStream = null;

		try {
			// pass directory path on server to connect
			ftpClient.connect(ip);

			// pass username and password, returned true if authentication is
			// successful
			boolean login = ftpClient.login("user", "password1");

			if (login) {
				System.out.println("Connection established...");
				File f = new File("testfile.txt");
				f.createNewFile();
				FileOutputStream fout = new FileOutputStream(f);

				fout.write("ftp forensic test".getBytes());
				fout.close();
				inputStream = new FileInputStream("testfile.txt");

				boolean uploaded = ftpClient.storeFile("test_file" + uuid
						+ ".txt", inputStream);
				inputStream = new FileInputStream("testfile.txt");

				if (uploaded) {
					System.out.println("File uploaded successfully !");
				} else {
					System.out.println("Error in uploading file !");
				}

				// logout the user, returned true if logout successfully
				boolean logout = ftpClient.logout();
				if (logout) {
					System.out.println("Connection close...");
				}
			} else {
				System.out.println("Connection fail...");
			}

		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				ftpClient.disconnect();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	public static void appendFile(String uuid, String ip) {

		FTPClient ftpClient = new FTPClient();
		FileInputStream inputStream = null;

		try {
			// pass directory path on server to connect
			ftpClient.connect(ip);

			// pass username and password, returned true if authentication is
			// successful
			boolean login = ftpClient.login("user", "password1");

			if (login) {
				System.out.println("Connection established...");
				File f = new File("testfile.txt");
				f.createNewFile();
				FileOutputStream fout = new FileOutputStream(f);

				fout.write("ftp forensic test".getBytes());
				fout.close();
				inputStream = new FileInputStream("testfile.txt");

				boolean append = ftpClient.appendFile("test_file" + uuid
						+ ".txt", inputStream);

				if (append) {
					System.out.println("File updated successfully !");
				} else {
					System.out.println("Error in updated file !");
				}

				// logout the user, returned true if logout successfully
				boolean logout = ftpClient.logout();
				if (logout) {
					System.out.println("Connection close...");
				}
			} else {
				System.out.println("Connection fail...");
			}

		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				ftpClient.disconnect();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

}
